//  这句话用来编程时自动提示，运行时需要注释掉！
//import * as BABYLON from '@babylonjs/core';

var canvas = document.getElementById("renderCanvas");

var startRenderLoop = function (engine, canvas) {
  engine.runRenderLoop(function () {
    if (sceneToRender && sceneToRender.activeCamera) {
      sceneToRender.render();
    }
  });
};

var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
  return new BABYLON.Engine(canvas, true, {
    preserveDrawingBuffer: true,
    stencil: true,
    disableWebGL2Support: false,
  });
};


//  创建场景（相关代码都在此处）
var createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  var scene = new BABYLON.Scene(engine);

  //  创建相机
  var camera = new BABYLON.ArcRotateCamera("camera", Math.PI / 2, 1.0, 10, BABYLON.Vector3.Zero());
  camera.attachControl(canvas, true);

  //  创建灯光
  var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));

  //  6个面的颜色
  const faceColors = [
    new BABYLON.Color3(1, 0, 0),
    new BABYLON.Color3(0, 1, 0),
    new BABYLON.Color3(0, 0, 1),
    new BABYLON.Color3(1, 1, 0),
    new BABYLON.Color3(1, 0, 1),
    new BABYLON.Color3(0, 1, 1)
  ];

  //  创建盒子(父对象)
  const boxParent = BABYLON.MeshBuilder.CreateBox("box", {faceColors: faceColors }, scene);
  //  创建盒子(子对象)
  const boxChild = BABYLON.MeshBuilder.CreateBox("boxChild", { size: 0.5, faceColors: faceColors }, scene);
  boxChild.position = new BABYLON.Vector3(0, 2, 0);
  boxParent.addChild(boxChild);

  //  子对象的平移和旋转仅影响子对象自身
  // 这里的顺序是xyz（不是根据代码顺序，而是根据旋转顺序）
  boxChild.rotation.x = Math.PI / 2;
  boxChild.rotation.y = Math.PI / 2;
  //  创建子对象的坐标轴
  const boxChildAxes = localAxis(1, scene);
  boxChildAxes.parent = boxChild;

  //  父对象的位置和旋转(位置和旋转独立的，先移动再旋转并无关联)
  boxParent.position = new BABYLON.Vector3(3, 0, 0);
  boxParent.rotation.z = Math.PI / 4;

  //  显示坐标轴
  showAxis(6, scene);

  //const text = makeTextPlane("X", "green", 1)
  return scene;
};

//  创建文字平面
const makeTextPlane = (text, color, size) => {
    const dynamicTexture = new BABYLON.DynamicTexture("dynamicTexture", 50, scene, true);
    dynamicTexture.hasAlpha = true;
    dynamicTexture.drawText(text, 5, 40, "bold 36px Arial", color, "transparent", true);

    const plane = BABYLON.MeshBuilder.CreatePlane("plane", {size:size, updatable:true}, scene);
    plane.material = new BABYLON.StandardMaterial("planeMat", scene);
    plane.material.backFaceCulling = false;
    plane.material.specularColor = new BABYLON.Color3(0, 0, 0);
    plane.material.diffuseTexture = dynamicTexture;
    return plane;
}

const showAxis = (length, scene) => {

  //  创建坐标轴x
  const xAxis = BABYLON.MeshBuilder.CreateLines("xAxis",
    { points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(length, 0, 0),
              new BABYLON.Vector3(length*0.95, 0.1, 0), new BABYLON.Vector3(length, 0, 0),
              new BABYLON.Vector3(length*0.95, -0.1, 0)] }, scene);
  xAxis.color = new BABYLON.Color3(1, 0, 0);
  const xText = makeTextPlane("X", "red", length/10.0);
  xText.position = new BABYLON.Vector3(length*0.95, -0.05*length, 0);

  //  创建坐标轴y
  const yAxis = BABYLON.MeshBuilder.CreateLines("yAxis",
    { points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, length, 0),
              new BABYLON.Vector3(-0.1, length*0.95, 0), new BABYLON.Vector3(0, length, 0),
              new BABYLON.Vector3(0.1, length*0.95, 0)] }, scene);
  yAxis.color = new BABYLON.Color3(0, 1, 0);
  const yText = makeTextPlane("Y", "green", length/10.0);
  yText.position = new BABYLON.Vector3(0.05*length, length*0.95, 0);

  //  创建坐标轴z
  const zAxis = BABYLON.MeshBuilder.CreateLines("zAxis",
    { points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, 0, length),
              new BABYLON.Vector3(0, -0.1, length*0.95), new BABYLON.Vector3(0, 0, length),
              new BABYLON.Vector3(0, 0.1, length*0.95)] }, scene);
  zAxis.color = new BABYLON.Color3(0, 0, 1);
  const zText = makeTextPlane("Z", "blue", length/10.0);
  zText.position = new BABYLON.Vector3(0.05*length, 0.05*length, length*0.95);
}


const localAxis = (length, scene) => {

  //  创建坐标轴x
  const xAxis = BABYLON.MeshBuilder.CreateLines("local_xAxis",
    { points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(length, 0, 0),
              new BABYLON.Vector3(length*0.95, 0.1, 0), new BABYLON.Vector3(length, 0, 0),
              new BABYLON.Vector3(length*0.95, -0.1, 0)] }, scene);
  xAxis.color = new BABYLON.Color3(1, 0, 0);

  //  创建坐标轴y
  const yAxis = BABYLON.MeshBuilder.CreateLines("local_yAxis",
    { points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, length, 0),
              new BABYLON.Vector3(-0.1, length*0.95, 0), new BABYLON.Vector3(0, length, 0),
              new BABYLON.Vector3(0.1, length*0.95, 0)] }, scene);
  yAxis.color = new BABYLON.Color3(0, 1, 0);

  //  创建坐标轴z
  const zAxis = BABYLON.MeshBuilder.CreateLines("local_zAxis",
    { points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, 0, length),
              new BABYLON.Vector3(0, -0.1, length*0.95), new BABYLON.Vector3(0, 0, length),
              new BABYLON.Vector3(0, 0.1, length*0.95)] }, scene);
  zAxis.color = new BABYLON.Color3(0, 0, 1);

  //  合并坐标轴(TransformNode不渲染)
  const local_origion = new BABYLON.TransformNode("local_origion", scene);

  local_origion.addChild(xAxis);
  local_origion.addChild(yAxis);
  local_origion.addChild(zAxis);

  return local_origion;
}



//================================================

window.initFunction = async function () {
  var asyncEngineCreation = async function () {
    try {
      return createDefaultEngine();
    } catch (e) {
      console.log(
        "the available createEngine function failed. Creating the default engine instead"
      );
      return createDefaultEngine();
    }
  };

  window.engine = await asyncEngineCreation();
  if (!engine) throw "engine should not be null.";
  startRenderLoop(engine, canvas);
  window.scene = createScene();
};
initFunction().then(() => {
  sceneToRender = scene;
});

// Resize
window.addEventListener("resize", function () {
  engine.resize();
});